#include <Windows.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>

#define VERSION "1.0.0"

typedef struct
{
    const char *file;
    double hscale;
    double vscale;
    size_t padding;
} OPT;

void parse_opt(OPT *opt, int argc, char *argv[]);
void print_help();
void print_version();
void write(OPT *opt);

int printf(const char *format, ...);
int puts(const char *);
__inline void exit(int);

__forceinline int _main(int argc, char *argv[])
{
    OPT opt;
    parse_opt(&opt, argc, argv);
    write(&opt);

    return 0;
}

__forceinline void write(OPT *opt)
{
    FILE *f = NULL;
    wchar_t *buf = NULL;
    DWORD len = 0;
    DWORD maxlen = 0;
    DWORD i;
    DWORD j;
    bool cont = true;
    HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

    if (opt->file)
        f = fopen(opt->file, "r");

    for (i = 0; cont; i = (i + 1) & 3)
    {
        for (j = 0;; j++)
        {

            int c = f ? fgetc(f) : getchar();
            switch (c)
            {
            case EOF:
                cont = false;
            case '\n':
                goto out;
            }
            if ((j >> 1) >= maxlen)
            {
                maxlen += 16;
                buf = realloc(buf, sizeof(wchar_t) * maxlen);
            }
            if ((j >> 1) >= len)
                buf[len++] = 0x2800;
            if (c != ' ')
                buf[j >> 1] |= 1 << (i > 2 ? 6 + (j & 1) : i + (j & 1) * 3);
        }
    out:
        if (!cont || i == 3)
        {
            WriteConsoleW(hStdOut, buf, len, NULL, 0);
            putchar('\n');
            len = 0;
        }
    }
    free(buf);
    if (f)
        fclose(f);
}

__forceinline void parse_opt(OPT *opt, int argc, char *argv[])
{
    int i = 1;
    opt->file = NULL;
    opt->hscale = 1;
    opt->vscale = 1;
    opt->padding = 0;

    for (i = 1; i < argc; i++)
    {
        if (argv[i][0] != '-')
        {
            opt->file = argv[i];
            continue;
        }

        if (argv[i][1] != '-')
        {
            switch (*(uint16_t *)&argv[i][1])
            {
            case 'H':
                opt->hscale = atof(argv[++i]);
                break;
            case 'V':
                opt->vscale = atof(argv[++i]);
                break;
            case 'v':
                print_version();
            case 'h':
            default:
                print_help(argv[0]);
                break;
            }

            continue;
        }

        if (!strcmp(argv[i] + 2, "help"))
            print_help(argv[0]);
        if (!strcmp(argv[i] + 2, "version"))
            print_version();

#define TEST(key, sub, s)                            \
    if (!strncmp(argv[i] + 2, key, sizeof(key) - 1)) \
    sscanf(argv[i] + 1 + sizeof(key), s, &opt->sub)

        TEST("horizontal-scale=", hscale, "%lf");
        else TEST("vertical-scale=", vscale, "%lf");
        else TEST("padding=", padding, "%zu");
    }
}

__forceinline void print_help(const char *exe_name)
{
    printf(
        "usage: %s OPTIONS FILE\n"
        "\n"
        "options:\n"
        "  -h, --help             show this help message and exit\n"
        "  -v, --version          print version and exit\n"
        "  -H, --horizontal-scale Specify horizontal scale factor, default: 1.0\n"
        "  -V, --vertical-scale   Specify vertical scale factor, default: 1.0\n"
        "  --padding              Specify padding width, optional\n",
        exe_name);
    exit(0);
}

__forceinline void print_version()
{
    puts(VERSION);
    exit(0);
}

__forceinline void exit(int code)
{
    ExitProcess(code);
}

void mainCRTStartup()
{
    int argc;
    char **argv;
    char **envp;
    int startup_info = 1;
    int __getmainargs(int *, LPSTR **, LPSTR **, int, int *);
    __getmainargs(&argc, &argv, &envp, 0, &startup_info);
    exit(_main(argc, argv));
}

long _fltused = 1;